﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CTS.Com.Domain.Exceptions;

namespace CTS.Com.Domain.Helper
{
    /// <summary>
    /// FileHelper
    /// </summary>
    public static class FileHelper
    {
        /// <summary>
        /// Lấy stream từ đường dẫn resource trong assembly
        /// </summary>
        /// <param name="type">Phần loại Assembly</param>
        /// <param name="resName">Đường dẫn resource</param>
        /// <returns>Stream</returns>
        public static Stream GetStream(Type type, string resName)
        {
            // Khai báo biến cục bộ
            var stream = type.Assembly.GetManifestResourceStream(resName);
            // Kết thúc xử lý trong trường hợp không tồn tại resource
            if (DataCheckHelper.IsNull(stream)) {
                throw new ExecuteException("E_MSG_00027", resName);
            }
            // Kết quả trả về
            return stream;
        }

        /// <summary>
        /// Đọc nội dung file từ đường dẫn
        /// </summary>
        /// <param name="path">Đường dẫn file</param>
        /// <returns>Chuỗi nội dung file</returns>
        public static string ToString(string path)
        {
            // Khai báo biến cục bộ
            var sb = new StringBuilder();
            // Tiến hành đọc file
            using (StreamReader reader = new StreamReader(path)) {
                sb.Clear();
                var line = string.Empty;
                while ((line = reader.ReadLine()) != null) {
                    sb.AppendLine(line);
                }
            }
            // Kết quả trả về
            return sb.ToString();
        }

        /// <summary>
        /// Đọc nội dung file từ stream
        /// </summary>
        /// <param name="stream">Stream file</param>
        /// <returns>Chuỗi nội dung file</returns>
        public static string ToString(Stream stream)
        {
            // Khai báo biến cục bộ
            var sb = new StringBuilder();
            // Tiến hành đọc file
            using (StreamReader reader = new StreamReader(stream)) {
                sb.Clear();
                var line = string.Empty;
                while ((line = reader.ReadLine()) != null) {
                    sb.AppendLine(line);
                }
            }
            // Kết quả trả về
            return sb.ToString();
        }

        /// <summary>
        /// Đọc nội dung file từ đường dẫn resource trong assembly
        /// </summary>
        /// <param name="type">Phần loại Assembly</param>
        /// <param name="resName">Đường dẫn resource</param>
        /// <returns>Chuỗi nội dung file</returns>
        public static string ToString(Type type, string resName)
        {
            // Lấy stream từ đường dẫn resource trong assembly
            var stream = GetStream(type, resName);
            // Đọc nội dung file từ stream
            return ToString(stream);
        }

        /// <summary>
        /// Tạo file
        /// </summary>
        /// <param name="path">Đường dẫn tạo file</param>
        public static void MakeFile(string path)
        {
            // Khai báo biến cục bộ
            var file = new FileInfo(path);
            var directory = file.Directory;
            // Tạo folder trong trường hợp đường dẫn không tồn tại
            if (!Directory.Exists(directory.FullName)) {
                Directory.CreateDirectory(directory.FullName);
            }
            // Tiến hành tạo file
            if (!File.Exists(file.FullName)) {
                File.Create(file.FullName).Close();
            }
        }

        /// <summary>
        /// Lưu file
        /// </summary>
        /// <param name="stream">Stream file</param>
        /// <param name="path">Đường dẫn lưu file</param>
        public static void SaveFile(Stream stream, string path)
        {
            // Khai báo biến cục bộ
            var file = new FileInfo(path);
            var directory = file.Directory;
            // Tạo folder trong trường hợp đường dẫn không tồn tại
            if (!Directory.Exists(directory.FullName)) {
                Directory.CreateDirectory(directory.FullName);
            }
            // Tiến hành tạo file
            var fileStream = File.Create(path);
            // Ghi nội dung vào file đã tạo
            using (fileStream) {
                stream.CopyTo(fileStream);
            }
        }

        /// <summary>
        /// Xóa file
        /// </summary>
        /// <param name="path">Đường dẫn file</param>
        /// <returns>True/False</returns>
        public static bool DeleteFile(string path)
        {
            // Trả về 'True' trong trường hợp file không tồn tại
            if (!File.Exists(path)) {
                return true;
            }
            // Lấy thông tin file
            var fileInfo = new FileInfo(path);
            // tiến hành xóa file
            try {
                fileInfo.Delete();
            } catch (Exception) {
                return false;
            }
            // Kết quả trả về
            return true;
        }

        /// <summary>
        /// Di chuyển file
        /// </summary>
        /// <param name="sourcePath">Đường dẫn file nguồn</param>
        /// <param name="targetPath">Đường dẫn file đến</param>
        public static void MoveFile(string sourcePath, string targetPath)
        {
            // Khai báo biến cục bộ
            var sourceFile = new FileInfo(sourcePath);
            var targetFile = new FileInfo(targetPath);
            // Kết thúc xử lý trong trường hợp file nguồn không tồn tại
            if (!sourceFile.Exists) {
                return;
            }
            // Xóa file đến trong trường hợp file đến đã tồn tại
            if (targetFile.Exists) {
                targetFile.Delete();
            }
            // Tạo folder trong trường hợp đường dẫn đến không tồn tại
            if (!Directory.Exists(targetFile.DirectoryName)) {
                Directory.CreateDirectory(targetFile.DirectoryName);
            }
            // Tiến hành di chuyển file
            sourceFile.MoveTo(targetFile.FullName);
        }

        /// <summary>
        /// Di chuyển nhiều file với phần mở rộng file cụ thể
        /// </summary>
        /// <param name="sourcePath">Đường dẫn nguồn</param>
        /// <param name="targetPath">Đường dẫn đến</param>
        /// <param name="ext">Phần mở rộng file</param>
        public static void MoveFiles(string sourcePath, string targetPath, string ext)
        {
            // Khai báo biến cục bộ
            var sourceFolder = new DirectoryInfo(sourcePath);
            var targetFolder = new DirectoryInfo(targetPath);
            // Trường hợp file nguồn không tồn tại
            if (!sourceFolder.Exists) {
                return;
            }
            // Tạo folder trong trường hợp đường dẫn đến không tồn tại
            if (!targetFolder.Exists) {
                Directory.CreateDirectory(targetFolder.FullName);
            }
            // Diệt các file trong đường dẫn nguồn với phần mở rộng file cụ thể
            foreach (var obj in sourceFolder.GetFiles(ext, SearchOption.TopDirectoryOnly)) {
                // Xóa file trong trường hợp đã tồn tại
                if (File.Exists(targetFolder.FullName + obj.Name)) {
                    File.Delete(targetFolder.FullName + obj.Name);
                }
                // Tiến hành di chuyển file
                obj.MoveTo(targetFolder.FullName + obj.Name);
            }
        }

        /// <summary>
        /// Sao chép nhiều file với phần mở rộng file cụ thể
        /// </summary>
        /// <param name="sourcePath">Đường dẫn nguồn</param>
        /// <param name="targetPath">Đường dẫn đến</param>
        /// <param name="ext">Phần mở rộng file</param>
        public static void CopyFiles(string sourcePath, string targetPath, string ext)
        {
            // Khai báo biến cục bộ
            var sourceFolder = new DirectoryInfo(sourcePath);
            var targetFolder = new DirectoryInfo(targetPath);
            // Kết thúc xử lý trong trường hợp đường dẫn nguồn không tồn tại
            if (!sourceFolder.Exists) {
                return;
            }
            // Tạo folder trong trường hợp đường dẫn đến không tồn tại
            if (!targetFolder.Exists) {
                Directory.CreateDirectory(targetFolder.FullName);
            }
            // Diệt các file trong đường dẫn nguồn với phần mở rộng file cụ thể
            foreach (var obj in sourceFolder.GetFiles(ext, SearchOption.TopDirectoryOnly)) {
                // Tiến hành sao chep file
                obj.CopyTo(targetFolder.FullName + obj.Name, true);
            }
        }

        /// <summary>
        /// Xóa nhiều file với phần mở rộng file cụ thể
        /// </summary>
        /// <param name="path">Đường dẫn xóa</param>
        /// <param name="ext">Phần mở rộng file</param>
        public static void DeleteFiles(string path, string ext)
        {
            // Khai báo biến cục bộ
            var folder = new DirectoryInfo(path);
            // Kết thúc xử lý trong trường hợp đường dẫn xóa không tồn tại
            if (!folder.Exists) {
                return;
            }
            // Diệt các file trong đường dẫn xóa với phần mở rộng file cụ thể
            foreach (var obj in folder.GetFiles(ext, SearchOption.TopDirectoryOnly)) {
                // Tiến hành xóa file
                obj.Delete();
            }
        }

        /// <summary>
        /// Lấy danh sách file với phần mở rộng file cụ thể
        /// </summary>
        /// <param name="path">Đường dẫn lấy</param>
        /// <param name="ext">Phần mở rộng file</param>
        /// <returns>Danh sách file</returns>
        public static IList<FileInfo> GetFiles(string path, string ext)
        {
            // Khai báo biến cục bộ
            var folder = new DirectoryInfo(path);
            var files = new List<FileInfo>();
            // Kết thúc xử lý trong trường hợp đường dẫn lấy không tồn tại
            if (!folder.Exists) {
                return files;
            }
            // Diệt các file trong đường dẫn lấy với phần mở rộng file cụ thể
            foreach (var obj in folder.GetFiles(ext, SearchOption.TopDirectoryOnly)) {
                files.Add(obj);
            }
            // Kết quả trả về
            return files;
        }

        /// <summary>
        /// Kiểm tra tồn tại file với phần mở rộng file cụ thể
        /// </summary>
        /// <param name="path">Đường dẫn kiễm tra</param>
        /// <param name="ext">Phần mở rộng file</param>
        /// <returns>True/False</returns>
        public static bool ExistFiles(string path, string ext)
        {
            // Lấy danh sách file với phần mở rộng file cụ thể
            var files = GetFiles(path, ext);
            // Kết quả trả về
            return (files != null && files.Count > 0);
        }

        /// <summary>
        /// Đọc file CSV
        /// </summary>
        /// <typeparam name="T">Phần loại đối tượng trả về</typeparam>
        /// <param name="path">Đường dẫn file</param>
        /// <returns>Danh sách record (T)</returns>
        public static IList<T> ReadCSV<T>(string path) where T : class, new()
        {
            // Khai báo biến cục bộ
            var result = DataHelper.CreateList<T>();
            var headerNames = DataHelper.CreateList<string>();
            var isFirst = true;
            // Tiến hành đọc file
            using (var reader = new StreamReader(path)) {
                var data = reader.ReadLine();
                while (!DataCheckHelper.IsNull(path)) {
                    var cols = DataHelper.SplitWithQuote(data, ',');
                    var obj = new T();
                    foreach (var value in cols) {
                        var index = cols.IndexOf(value);
                        if (isFirst) {
                            headerNames.Add(value);
                        } else {
                            DataHelper.SetProperty(obj, headerNames[index], value);
                        }
                    }
                    if (!isFirst) {
                        result.Add(obj);
                    }
                    isFirst = false;
                    data = reader.ReadLine();
                }
            }
            // Kết quả trả về
            return result;
        }
    }
}
